﻿using System.Reflection;
using System.Runtime.CompilerServices;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualBasic;
using System.Runtime.Loader;
using System.IO;
using BabyStroll.SDK;
using System.Diagnostics;
using System.Security.Cryptography.X509Certificates;

namespace Program
{
    //接口
    public class Program
    {
        //接口
        #region
        public static void Main1(string[] args)
        {
            PowerSupply powerSupply = new PowerSupply();
            DeskFan deskFan = new DeskFan(powerSupply);
            Console.WriteLine(deskFan.Work());
        }
        public interface IPowerSupply
        {
            int GetPower();
        }
        public class PowerSupply:IPowerSupply
        {
            public int GetPower()
            {
                return 100;
            }
        }
        public class DeskFan
        {
            IPowerSupply _powerSupply;
            public DeskFan(IPowerSupply powerSupply)
            {
                _powerSupply = powerSupply;
            }
            public string Work()
            {
                int power = _powerSupply.GetPower();
                if (power <= 0)
                {
                    return "Won't Work";
                }
                else if (power < 100)
                {
                    return "Run Slowly";
                }
                else if (power < 200)
                {
                    return "Normal";
                }
                else
                {
                    return "Warning";
                }
            }
        }
        #endregion
        //接口隔离原则
        #region
        static void Main12(string[] args)
        {
            //创建 HeavyTank 实例并使用反射调用方法
            ITank tank = new HeavyTank();
            var driverType = tank.GetType();
            object o = Activator.CreateInstance(driverType);//使用 Activator.CreateInstance 方法根据 driverType 动态创建一个新的 HeavyTank 对象实例，
                                                            //返回一个 object 类型的引用。
            MethodInfo fireMI = driverType.GetMethod("Fire");
            MethodInfo runMI = driverType.GetMethod("Run");
            fireMI.Invoke(o,null);//由于 Fire 和 Run 方法没有参数，所以传入 null。
            runMI.Invoke(o,null);

            //创建 Truck 实例并使用反射调用方法
            IVehicle vehicle = new Truck();
            var driverV = vehicle.GetType();
            object oV = Activator.CreateInstance(driverV);
            MethodInfo runVMI = driverV.GetMethod("Run");
            runVMI.Invoke(oV,null);
        }
        class Driver :IVehicle
        {
            public IVehicle _vehicle;
            public Driver(IVehicle vehicle)
            {
                _vehicle = vehicle;
            }

            public void Run()
            {
                _vehicle.Run();
            }
        }
        interface IVehicle
        {
            void Run();
        }
        interface IWeapon
        {
            void Fire();
        }
        class Car : IVehicle
        {
            public void Run()
            {
                Console.WriteLine("Car is Running");
            }
        }
        class Truck : IVehicle
        {
            public void Run()
            {
                Console.WriteLine("Truck is Running");
            }
        }
        interface ITank:IWeapon,IVehicle
        {
        }
        class TankDriver : ITank
        {
            ITank _tank = new Tank();
            public TankDriver(ITank tank)
            {
                _tank = tank;
            }
            public void Fire()
            {
                _tank.Fire();
            }

            public void Run()
            {
                _tank.Run();
            }
        }
        class Tank : ITank
        {
            public void Run()
            {
                Console.WriteLine("Tank Running");
            }

            public void Fire()
            {
                Console.WriteLine("Tank Firing");
            }

        }
        class LightTank : ITank
        {
            public void Fire()
            {
                Console.WriteLine("LightTank Firing");
            }

            public void Run()
            {
                Console.WriteLine("LightTank Running");
            }
        }
        class HeavyTank : ITank
        {
            public void Fire()
            {
                Console.WriteLine("HeavyTank Firing");
            }

            public void Run()
            {
                Console.WriteLine("HeavyTank Running");
            }
        }
        #endregion
        //反射的第一个用途：依赖注入DI
        #region
        static void Main3(string[] args)
        {
            var sc =new ServiceCollection();//ServiceCollection 是依赖注入容器的配置类，用于注册服务。
            sc.AddScoped(typeof(ITank),typeof(HeavyTank));//AddScoped 方法用于将服务注册到容器中。
            sc.AddScoped(typeof(IVehicle),typeof(HeavyTank));
            sc.AddScoped(typeof(IVehicle),typeof(Truck));
            sc.AddScoped(typeof(IVehicle),typeof(Car));//需要注意的是，最后一次注册的服务会覆盖之前的注册，
                                                       //所以当请求 IVehicle 类型的服务时，容器将返回 Car 类的实例。
            //sc.AddScoped(typeof(ITank), typeof(HeavyTank));
            sc.AddScoped<Driver>();
            sc.AddScoped<TankDriver>();
            sc.AddScoped<Truck>();
            var sp = sc.BuildServiceProvider();//用于构建服务提供者（ServiceProvider），
                                               //它是依赖注入容器的核心，负责解析和提供服务。

            //下面为应用
            var driver = sp.GetService<Driver>();//GetService 方法用于从服务提供者中获取指定类型的服务实例。
            driver.Run();
            var tankDriver = sp.GetService<TankDriver>();//创建一个 TankDriver 实例，并将一个 HeavyTank 实例注入到其构造函数中。
            tankDriver.Fire();
            var trunkDriver = sp.GetService<Truck>();
            trunkDriver.Run();
           /* var heavyTank = sp.GetService<HeavyTank>();
            heavyTank.Fire();*/
        }
        #endregion

        //反射的第二个用途：更松耦合,主体程序与插件，
        //API（application program interface），SDK（software development kit）
        static void Main121(string[] args) 
        {
            var folder = Path.Combine(Environment.CurrentDirectory,"Animals");//模仿外部插件的文件夹
            var files = Directory.GetFiles(folder);//获取"Animals"的文件夹
            var animalsType = new List<Type>();
            foreach (var file in files) 
            {
                var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(file);//遍历文件夹下的文件
                var types = assembly.GetTypes();
                foreach (var type in types)
                {
                    if (type.GetInterfaces().Contains(typeof(IAnimal)))//筛选出实现了 IAnimal 接口的类型
                    {
                        bool isUnfinished = type.GetCustomAttributes(false).Any(a => a.GetType() == typeof(UnfinishedAttribute));//获取带有方法特性的方法
                        if (!isUnfinished)
                        {
                            animalsType.Add(type);
                        }
                    }
                    /*if (type.GetMethod("Voice") != null)//获取没有方法特性的方法,所有Voice方法
                    {
                        animalsType.Add(type);
                    }*/
                }
            }

            while (true)
            {
                for(int i = 0;i< animalsType.Count; i++)
                {
                    Console.WriteLine($"{i + 1},{animalsType[i].Name}");
                }
                Console.WriteLine("============================");
                Console.WriteLine("Please choose animal");
                var index = int.Parse(Console.ReadLine());
                if(index < 0 && index > animalsType.Count)
                {
                    Console.WriteLine("Please input correct number");
                }
                var times = int.Parse(Console.ReadLine());
                var t = animalsType[index-1];
                var o = Activator.CreateInstance(t);
                var m = t.GetMethod("Voice");
                m.Invoke(o, new object[] { times });
            }
        }

    }
    //泛型,正交性，泛型类，泛型接口，泛型数据结构,
    public class Generic
    {
        //泛型类
        #region
        static void Main1(string[] args)
        {
            //类型膨胀,每次新增新的类都要新的实例化
            //Apple apple = new Apple() { Color = "Red"};
            //AppleBox appleBox = new AppleBox() { Cargo = apple };
            //Console.WriteLine(appleBox.Cargo.Color);
            //Book book = new Book() {Name = "New Book" };
            //BookBox bookBox = new BookBox() { BookName = book};
            //Console.WriteLine(bookBox.BookName.Name);

            //成员膨胀
            //Apple apple = new Apple() { Color = "Green" };
            //Book book = new Book() { Name = "New Book" };
            //Box appleBox = new Box() { Apple = apple};
            //Box bookBox = new Box() { Book = book};
            //Console.WriteLine(appleBox.Apple.Color);
            //Console.WriteLine(bookBox.Book.Name);

            //使用object字段，强制类型转化也会麻烦
            //Apple apple = new Apple() { Color = "Green" };
            //Book book = new Book() { Name = "New Book" };
            //Box appleBox = new Box() { Cargo = apple};
            //Console.WriteLine((appleBox.Cargo as Apple)?.Color);

            //使用泛型，既不产生类型膨胀和成员膨胀
            Apple apple = new Apple() { Color = "Yellow"};
            Book book = new Book() { Name = "水浒传"};
            Box<Apple> appleBox = new Box<Apple>() { Cargon = apple};
            Box<Book> bookBox = new Box<Book>() { Cargon = book};
            Console.WriteLine(appleBox.Cargon.Color);
            Console.WriteLine(bookBox.Cargon.Name);
        }
        //泛型，泛化类型
        class Box<TCargon>
        {
            public TCargon Cargon {  get; set; } 
            //public Object Cargo {  get; set; }
            //public Apple Apple { get; set; }
            //public Book Book { get; set; }
        }
        class Apple
        {
            public string Color { get; set; }
        }
        class AppleBox
        {
            public Apple Cargo { get; set; }
        }

        class Book
        {
            public string Name { get; set; }
        }
        class BookBox
        {
            public Book BookName { get; set; }
        }
        #endregion
        //=========================================================================
        //泛型接口
        #region
        static void Main3(string[] args)
        {
            //Student<long> student = new Student<long>();
            Student student = new Student();
            var id = student.Id = 1111111111111111;
            var name = student.Name= "Test";
            Console.WriteLine($"{id}{name}");
            //=====================================
            IList<int> ints = new List<int>();
            for (int i = 0; i < 10; i++)
            {
                ints.Add(i);
            }
            foreach(int i in ints)
            {
                Console.WriteLine(i);
            }
            //==========多态特化类型===========================
            IDictionary<int,string> keyValuePairs = new Dictionary<int, string>();
            keyValuePairs[1] = "Test1";
            keyValuePairs[2] = "Test2";
            Console.WriteLine($"KeyValuePairs #1 is {keyValuePairs[1]},#2 is {keyValuePairs[2]}");
            //================================================
        }
        interface IUnique<TID> 
        {
            public  TID Id { get; set; }
        }
        //①泛型类实现泛型接口
        class Student<TId> : IUnique<TId>
        {
            public TId Id { get; set; }
            public string Name { get; set; }
        }
        //②
        class Student : IUnique<ulong>
        {
            public ulong Id { get ; set ; }
            public string Name { get; set; }
        }
        #endregion
    }
} 